function jsGL()
{
  this.Projection = 0;
  this.ModelView = 1;
  
  this.matrixMode = this.Projection;
  
  this.matrixList = Array();
  this.matrixList.push(this.identity());
  this.matrixList.push(this.identity());
  
  this.matrixStack = Array();
  this.matrixStack.push(Array());
  this.matrixStack.push(Array());
}

jsGL.prototype.push = function ()
{
  this.matrixStack[this.matrixMode].push(this.matrixList[this.matrixMode].clone());
}

jsGL.prototype.pop = function ()
{
  this.matrixList[this.matrixMode] = this.matrixStack[this.matrixMode].pop();
}

jsGL.prototype.setMode = function (mode)
{
  this.matrixMode = mode;
}

jsGL.prototype.loadMatrix = function (matrix)
{
  this.matrixList[this.matrixMode] = matrix;
}

jsGL.prototype.rotate = function (angle,x,y,z)
{
  var c = Math.cos(angle);
  var c1 = 1 - c;
  var s = Math.sin(angle);
  var xx = x * x;
  var xy = x * y;
  var xz = x * z;
  var yy = y * y;
  var yz = y * z;
  var zz = z * z;
  var xs = x * s;
  var ys = y * s;
  var zs = z * s;
  
  return new Matrix(4,4,[ [xx * c1 + c,   xy * c1 - zs,   xz * c1 - ys, 0],
                          [xy * c1 + zs,  yy * c1 + c,    yz * c1 - xs, 0],
                          [xz * c1 - ys,  yz * c1 + xs,   zz * c1 + c,  0],
                          [0,             0,              0,            1]]);  
}

jsGL.prototype.translate = function (x,y,z)
{
  return new Matrix(4,4,[ [1,0,0,x],
                          [0,1,0,y],
                          [0,0,1,z],
                          [0,0,0,1]]); 
}

jsGL.prototype.scale = function (x,y,z)
{
  return new Matrix(4,4,[ [x,0,0,0],
                          [0,y,0,0],
                          [0,0,z,0],
                          [0,0,0,1]]); 
}

jsGL.prototype.frustum = function (left, right, bottom, top, near, far)
{
  var a = (right + left) / (right - left);
  var b = (top + bottom) / (top - bottom);
  var c = (far + near) / (far - near);
  var d = -(2 * far * near) / (far - near);
  var e = (2 * near) / (right - left);
  var f = (2 * near) / (top - bottom);
  
  return new Matrix(4,4,[ [e,0, a,0],
                          [0,f, b,0],
                          [0,0, c,d],
                          [0,0,-1,0]]);  
}

jsGL.prototype.perspective = function (fovY,aspect,near,far)
{
  var f = 1.0 / Math.tan(fovY / 2);
  var a = (2 * far * near) / (near - far);
  var b = (far + near) / (near - far);
  var c = f / aspect;
  
  return new Matrix(4,4,[ [c,0, 0,0],
                          [0,f, 0,0],
                          [0,0, b,a],
                          [0,0,-1,0]]);  
}

jsGL.prototype.orthographic = function (left,right,buttom,top,near,far)
{
  var a = 2 / (right - left);
  var b = 2 / (top - bottom);
  var c = -2 / (far - near);
  var d = -(right + left) / (right - left);
  var e = -(top + bottom) / (top - bottom);
  var f = -(far + near) / (far - near);

  return new Matrix(4,4,[ [a,0,0,d],
                          [0,b,0,e],
                          [0,0,c,f],
                          [0,0,0,1]]);  
}

jsGL.prototype.identity = function ()
{
  return new Matrix(4,4,[ [1,0,0,0],
                          [0,1,0,0],
                          [0,0,1,0],
                          [0,0,0,1]]);
}
